﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data;
using System.Reflection;
using System.Collections;
using System.ComponentModel;
using System.Management;
using System.Management.Instrumentation;
using System.Windows.Forms;
using YY.UI.BaseDataSvc;
using YY.Common;
using System.Net;
using System.Drawing;

namespace YY.UI
{
    #region 系统登陆用户信息
    /// <summary>
    /// 系统登陆用户信息
    /// </summary>
    public static class SysLoginUserInfo
    {
        static int _UserId;
        /// <summary>
        /// 系统登陆用户编号
        /// </summary>
        public static int UserId { get { return _UserId; } set { _UserId = value; Artech.ContextPropagation.ApplicationContext.Current.UserId = value; } }

        /// <summary>
        /// 系统登陆用户名称
        /// </summary>
        public static string UserName { get; set; }
        /// <summary>
        /// 用户代号
        /// </summary>
        public static string UserCode { get; set; }
        /// <summary>
        /// 用户ip地址
        /// </summary>
        public static string[] IPs { get; set; }
        /// <summary>
        /// 用户机器所有Mac地址
        /// </summary>
        public static string[] Macs { get; set; }

        /// <summary>
        /// 用户登录时间
        /// </summary>
        public static DateTime LoginTime { get; set; }

        static int _Role;
        /// <summary>
        /// 用户角色
        /// </summary>
        public static int Role { get { return _Role; } set { _Role = value; Artech.ContextPropagation.ApplicationContext.Current.Role = value; } }

        public static bool IsAdministrator { get; set; }
    }
    #endregion

    #region 通用方法
    public static class Common
    {
        #region 枚举
        /// <summary>
        /// 保存方式枚举
        /// </summary>
        public enum SaveMode
        {
            /// <summary>
            /// 保存
            /// </summary>
            Save,
            /// <summary>
            /// 保存并新建
            /// </summary>
            SaveAndNew,
            /// <summary>
            /// 保存并关闭
            /// </summary>
            SaveAndClose
        }

        /// <summary>
        /// 窗体委托回调操作类型
        /// </summary>
        public enum OperateType
        {
            /// <summary>
            /// 新增操作
            /// </summary>
            Add = 1,
            /// <summary>
            /// 更新操作
            /// </summary>
            Update,
            /// <summary>
            /// 删除操作
            /// </summary>
            Delete
        }

        /// <summary>
        /// 单据窗体操作类型, BaseFrm 中 EditStatus 属性使用。
        /// </summary>
        public enum BillOperateType
        {
            /// <summary>
            /// 新增操作
            /// </summary>
            Add,
            /// <summary>
            /// 更新操作
            /// </summary>
            Update,
            /// <summary>
            /// 删除操作
            /// </summary>
            Delete,
            /// <summary>
            /// 查看操作
            /// </summary>
            View,
            /// <summary>
            /// 无操作
            /// </summary>
            None
        }

        #endregion

        #region 右键菜单
        /// <summary>
        /// 添加右键菜单项
        /// </summary>
        /// <param name="text">要显示的菜单文字，如果为空则显示为分割线</param>
        /// <param name="cms">要添加到的子菜单集合</param>
        /// <param name="callback">点击时触发的事件</param>
        /// <param name="enable">菜单是否可用</param>
        /// <param name="chcd">菜单是否勾选中</param>
        /// <param name="tag">菜单tag</param>
        /// <returns>生成的子菜单，如果为分隔条则返回null</returns>
        public static ToolStripMenuItem AddContextMenu(string text, ToolStripItemCollection cms, EventHandler callback, bool enable, bool chcd, object tag)
        {
            if (text == string.Empty)
            {
                ToolStripSeparator tsp = new ToolStripSeparator();
                cms.Add(tsp);
            }
            else
            {
                ToolStripMenuItem tsmi = new ToolStripMenuItem(text);
                if (callback != null)
                    tsmi.Click += callback;
                tsmi.Enabled = enable;
                tsmi.Checked = chcd;
                tsmi.Tag = tag;
                cms.Add(tsmi);
                return tsmi;
            }
            return null;
        }
        #endregion

        #region 获取客户端IP、MAC地址
        /// <summary>
        /// 返回当前机器所有IP地址
        /// </summary>
        /// <returns></returns>
        public static string[] GetIP()
        {
            try
            {
                ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                ManagementObjectCollection moc = mc.GetInstances();
                List<string> ips = new List<string>();
                foreach (ManagementObject mo in moc)
                {
                    if ((bool)mo["IPEnabled"] == true)
                    { ips.Add((mo["IPAddress"] as string[])[0]); }
                    //strIP = strIP + "|" + (mo["IPAddress"] as string[])[0];
                }
                return ips.ToArray();
            }
            catch { }
            return null;
        }

        /// <summary>
        /// 返回当前机器上的所有MAC地址
        /// </summary>
        /// <returns></returns>
        public static string[] GetMac()
        {
            try
            {
                ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
                ManagementObjectCollection moc = mc.GetInstances();
                List<string> macs = new List<string>();
                foreach (ManagementObject mo in moc)
                {
                    if ((bool)mo["IPEnabled"] == true)
                    { macs.Add(mo["MacAddress"].ToString()); }
                    //strMac = strMac + "|" + mo["MacAddress"].ToString();
                }
                return macs.ToArray();
            }
            catch { }
            return null;
        }

        #endregion

        /// <summary>
        /// MDI窗口是否已经被打开
        /// 已打开的放到最顶层，没打开的创建实例
        /// </summary>
        /// <param name="parentFrm"></param>
        /// <param name="childFrmName"></param>
        /// <returns></returns>
        public static bool MdiFrmIsOpened(Form parentFrm, string childFrmName)
        {
            bool open = false;
            for (int i = 0; i < parentFrm.MdiChildren.Length; i++)
            {
                if (parentFrm.MdiChildren[i].Name == childFrmName)
                {
                    parentFrm.MdiChildren[i].BringToFront();
                    open = true;
                    break;
                }
            }
            return open;
        }

        #region 绑定数据到ComboBox\DataGridViewComboBoxColumn

        /// <summary>
        /// 绑定枚举数据到DataGridViewComboBoxColumn
        /// </summary>
        /// <param name="cb"></param>
        /// <param name="enmType"></param>
        /// <param name="exceptNames"></param>
        public static void BindEnumToDataGridViewComboBoxColumn(DataGridViewComboBoxColumn cbc, Type enmType)
        {
            cbc.Items.Clear();
            foreach (string s in Enum.GetNames(enmType))
                cbc.Items.Add(s);
        }

        /// <summary>
        /// 绑定枚举数据到ComboBox
        /// </summary>
        /// <param name="cb"></param>
        /// <param name="enmType"></param>
        /// <param name="exceptNames"></param>
        public static void BindEnumToComboBox(ComboBox cb, Type enmType, object selectedItem)
        {
            BindEnumToComboBox(cb, enmType, null, selectedItem);
        }

        /// <summary>
        /// 绑定枚举数据到ComboBox
        /// </summary>
        /// <param name="cb"></param>
        /// <param name="enmType"></param>
        /// <param name="exceptNames"></param>
        public static void BindEnumToComboBox(ComboBox cb, Type enmType, string[] exceptNames, object selectedItem)
        {
            cb.Items.Clear();
            foreach (string s in Enum.GetNames(enmType))
            {
                if (exceptNames != null)
                {
                    if (!exceptNames.Contains(s))
                        cb.Items.Add(s);
                }
                else
                    cb.Items.Add(s);
            }
            if (selectedItem != null)
                cb.SelectedItem = selectedItem;
        }

        /// <summary>
        /// 通用选项数据绑定treeview树
        /// </summary>
        /// <param name="tv">传入TreeView</param>
        /// <param name="options">通用选项数据</param>
        /// <param name="rootName">显示根节点名称</param>
        public static void BindOptionTree(TreeView tv, TB_Options[] options, string rootName)
        {
            if (tv.Nodes.Count > 0)
                tv.Nodes.Clear();
            TreeNode node = new TreeNode(rootName);
            node.ImageIndex = 1;
            initChild(node, options, 0);
            tv.Nodes.Add(node);
            tv.SelectedNode = node;
            tv.ExpandAll();
        }

        private static void initChild(TreeNode node, TB_Options[] options, int parentId)
        {
            var ops = from o in options where o.parentId == parentId select o;
            if (options != null)
            {
                foreach (TB_Options child in ops)
                {
                    TreeNode newNode = node.Nodes.Add(child.id.ToString(), child.code + "[" + child.name + "]");
                    newNode.Tag = child;
                    newNode.ImageIndex = 2;
                    initChild(newNode, options, child.id);
                }
            }
        }

        /// <summary>
        /// 绑定一类通用分类数据到DataGridViewComboBoxColumn
        /// </summary>
        /// <param name="cbBox"></param>
        /// <param name="options"></param>
        /// <param name="ot"></param>
        public static void BindOptionsDataGridViewComboBoxColumn(DataGridViewComboBoxColumn cbc, IEnumerable<TB_Options> options, EnumCommon.OptionType ot)
        {
            if (options != null)
            {
                IEnumerable<TB_Options> tempOptions = options.Where(p => p.type == ot.ToString());
                cbc.Tag = ot;
                cbc.Items.Clear();
                if (tempOptions != null)
                {
                    cbc.DisplayMember = "name";
                    cbc.ValueMember = "id";
                    cbc.Items.AddRange(tempOptions.ToArray());
                }
            }
        }

        /// <summary>
        /// 绑定一类通用分类数据到ComboBox
        /// </summary>
        /// <param name="cbBox"></param>
        /// <param name="options"></param>
        /// <param name="ot"></param>
        public static void BindOptionsComboBox(ComboBox cbBox, IEnumerable<TB_Options> options, EnumCommon.OptionType ot)
        {
            if (options != null)
            {
                IEnumerable<TB_Options> tempOptions = options.Where(p => p.type == ot.ToString());
                cbBox.DataSource = null;
                cbBox.Tag = ot;
                cbBox.Items.Clear();
                if (tempOptions != null)
                {
                    cbBox.DisplayMember = "name";
                    cbBox.ValueMember = "id";
                    cbBox.Items.AddRange(tempOptions.ToArray());
                }
            }
        }

        /// <summary>
        /// 通用分类ComboBox选中Option类型项目
        /// </summary>
        /// <param name="cbBox">ComboBox</param>
        /// <param name="options">数据源</param>
        /// <param name="ot">分类类型</param>
        /// <param name="id">选中值</param>
        public static void SelectedOptionsComboBox(ComboBox cbBox, IEnumerable<TB_Options> options, EnumCommon.OptionType ot, int? id)
        {
            if (options != null && id != null)
                cbBox.SelectedItem = options.SingleOrDefault(p => p.type == ot.ToString() && p.id == id);
        }

        /// <summary>
        /// 模糊匹配通用分类数据
        /// </summary>
        /// <param name="cbBox"></param>
        /// <param name="datas"></param>
        /// <param name="senderFrm"></param>
        /// <param name="ot"></param>
        public static void ComboBoxMatchOption(ComboBox cbBox, TB_Options[] datas, Form senderFrm, EnumCommon.OptionType ot)
        {
            cbBox.DataSource = datas;
            if (cbBox.SelectedItem == null)
            {
                if (MessageBox.Show("查无该选项，现在去添加吗？", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    OptionFrm frm = new OptionFrm();
                    frm.Text = ot.ToString() + "管理";
                    frm.OType = ot;
                    frm.SearchMode = true;
                    if (frm.ShowDialog(senderFrm) == DialogResult.OK)
                    {
                        cbBox.DataSource = null;
                        Common.BindOptionsComboBox(cbBox, new TB_Options[] { frm.SelectorItem as TB_Options }, ot);
                        cbBox.SelectedIndex = 0;
                    }
                }
                else
                    cbBox.Text = null;
            }
        }

        /// <summary>
        /// 绑定数据到ComboBox
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cbBox"></param>
        /// <param name="datas"></param>
        /// <param name="displayMember"></param>
        /// <param name="valueMember"></param>
        public static void ComboBoxBindDatas<T>(ComboBox cbBox, IEnumerable<T> datas, string displayMember, string valueMember)
        {
            if (datas != null)
            {
                cbBox.DataSource = null;
                cbBox.Items.Clear();
                cbBox.DisplayMember = displayMember;
                cbBox.ValueMember = valueMember;
                foreach (T obj in datas)
                    cbBox.Items.Add(obj);
            }
        }

        public static void SetComboBoxDropDownList(ComboBox cbBox, object nullObject)
        {
            cbBox.DropDownStyle = ComboBoxStyle.DropDownList;
            int index = cbBox.Items.Add(nullObject);
            cbBox.SelectedIndex = index;
        }

        /// <summary>
        /// 模糊匹配用户序列数据
        /// </summary>
        /// <param name="cbBox"></param>
        /// <param name="datas"></param>
        /// <param name="senderFrm"></param>
        public static void ComboBoxMatchUser(ComboBox cbBox, TB_User[] datas, Form senderFrm)
        {
            cbBox.DataSource = datas;
            if (cbBox.SelectedItem == null)
            {
                if (MessageBox.Show("查无该选项，现在去添加吗？", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    UserFrm frm = new UserFrm();
                    frm.SearchMode = true;
                    if (frm.ShowDialog(senderFrm) == DialogResult.OK)
                    {
                        cbBox.DataSource = null;
                        cbBox.DisplayMember = "userName";
                        cbBox.ValueMember = "id";
                        int index = cbBox.Items.Add(frm.SelectorItem);
                        cbBox.SelectedIndex = index;
                    }
                }
                else
                    cbBox.Text = null;
            }
        }

        /// <summary>
        /// 模糊匹配客户序列数据
        /// </summary>
        /// <param name="cbBox"></param>
        /// <param name="datas"></param>
        /// <param name="senderFrm"></param>
        public static void ComboBoxMatchClient(ComboBox cbBox, TB_Clients[] datas, Form senderFrm)
        {
            cbBox.DataSource = datas;
            if (cbBox.SelectedItem == null)
            {
                if (MessageBox.Show("查无该选项，现在去添加吗？", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    ClientFrm frm = new ClientFrm();
                    frm.SearchMode = true;
                    if (frm.ShowDialog(senderFrm) == DialogResult.OK)
                    {
                        cbBox.DataSource = null;
                        cbBox.DisplayMember = "fullName";
                        cbBox.ValueMember = "id";
                        int index = cbBox.Items.Add(frm.SelectorItem);
                        cbBox.SelectedIndex = index;
                    }
                }
                else
                    cbBox.Text = null;
            }
        }
        #endregion

        #region DataGridView通用
        /// <summary>
        /// 动态绑定DGV列架构
        /// </summary>
        /// <param name="dgv">DataGridView</param>
        /// <param name="dgc">DataGridViewColumn类型</param>
        /// <param name="dataPropertyName">绑定数据列名称</param>
        /// <param name="headerText">列标题文本</param>
        /// <param name="visible">是否可见</param>
        /// <param name="readOnly">是否只读</param>
        /// <param name="width">设置宽度</param>
        /// <returns></returns>
        public static int AddDgvColumn(DataGridView dgv, DataGridViewColumn dgc, string dataPropertyName, string headerText, bool? visible, bool? readOnly, int? width)
        {
            try
            {
                dgc.HeaderText = headerText;
                dgc.DataPropertyName = dataPropertyName;
                dgc.Name = "Column_" + (dgv.Columns.Count + 1).ToString();
                if (visible != null)
                    dgc.Visible = Convert.ToBoolean(visible);
                if (readOnly != null)
                    dgc.ReadOnly = Convert.ToBoolean(readOnly);
                if (width != null)
                    dgc.Width = (int)width;
                if (!dgv.Columns.Contains(dgc.Name))
                    return dgv.Columns.Add(dgc);
            }
            catch { }
            return 0;
        }
        #endregion

        /// <summary>
        /// 重置窗体清除数据
        /// </summary>
        /// <param name="pCtrl">所属控件</param>
        /// <param name="ts">指定控件序列</param>
        public static void ClearForm(Control pCtrl, Type[] ts)
        {
            for (int i = 0; i < pCtrl.Controls.Count; i++)
            {
                Type t = pCtrl.Controls[i].GetType();
                if (ts != null && !ts.Contains(t))
                {
                    if (t.Equals(typeof(ComboBox)))
                        ((ComboBox)pCtrl.Controls[i]).SelectedItem = null;
                    else if (t.Equals(typeof(TextBox)))
                        ((TextBox)pCtrl.Controls[i]).Text = string.Empty;
                }
            }
        }
        /// <summary>
        /// 窗体控件重置
        /// </summary>
        /// <param name="pCtrl"></param>
        /// <param name="excepts"></param>
        public static void ResetControl(Control pCtrl, string[] excepts)
        {
            foreach (Control ctrl in pCtrl.Controls)
            {
                if (excepts != null)
                    if (excepts.Any(p => p == ctrl.Name))
                        continue;
                if (ctrl is TextBox)
                    (ctrl as TextBox).Text = null;
                else if (ctrl is ComboBox)
                    (ctrl as ComboBox).SelectedItem = null;
            }
        }

        /// <summary>
        /// 获取控件值到数据对象属性
        /// </summary>
        /// <param name="dataObj">数据对象</param>
        /// <param name="propName">数据属性名</param>
        /// <param name="ctrlVal">控件值</param>
        public static void EvalControlValueToData(object dataObj, string propName, object ctrlVal)
        {
            if (ctrlVal != null)
            {
                PropertyInfo pi = dataObj.GetType().GetProperty(propName);
                Type t = pi.PropertyType;
                if ((t.IsGenericType) && (t.GetGenericTypeDefinition() == typeof(Nullable<>)))
                    t = t.GetGenericArguments()[0];
                object nValue = Convert.ChangeType(ctrlVal, t);
                pi.SetValue(dataObj, nValue, null);
            }
        }
        #region 文件下载
        /// <summary>
        /// 下载服务器文件至客户端
        /// </summary>
        /// <param name="URL">被下载的文件地址，绝对路径</param>
        /// <param name="Dir">另存放的目录</param>
        public static void DownloadFile(string url, string Dir)
        {

            string fileName = url.Substring(url.LastIndexOf("//") + 1);  //被下载的文件名
            string Path = Dir + fileName;   //另存为的绝对路径＋文件名
            try
            {
                //WebRequest myre = WebRequest.Create(url);
                using (WebClient client = new WebClient())
                {
                    client.DownloadFile(url, Path);
                    client.Dispose();
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        /// <summary>
        /// 操作是否合法
        /// </summary>
        /// <param name="objs">用户模块权限定义数据</param>
        /// <param name="opKey">操作关键字</param>
        /// <returns></returns>
        public static bool IsActionPermit(IEnumerable<TB_ActionPermission> objs, EnumCommon.PermissionOpType opType)
        {
            if (SysLoginUserInfo.Role.Equals((int)EnumCommon.SysRoleType.管理员))//管理员不受限制
                return true;
            try
            {
                if (objs != null)
                { return objs.Any(p => p.opKey == Enum.GetName(typeof(EnumCommon.PermissionOpType), opType)); }
            }
            catch { }
            return false;
        }

        /// <summary>
        /// DataGridView在行标题列显示行号
        /// 确保RowsHeaderWidthSizeMode属性设置为AutoSizeToAllHeaders或者AutoSizeToDisplayedHeaders以适应文字宽度
        /// 在RowsAdded和RowsRemoved事件里触发
        /// </summary>
        /// <param name="dgv"></param>
        public static void ShowDataGridViewRowNo(object sender)
        {
            DataGridView dgv = sender as DataGridView;
            for (int i = 0; i < dgv.RowCount; i++)
            {
                dgv.Rows[i].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft;
                dgv.Rows[i].HeaderCell.Value = (i + 1).ToString();
            }
        }

        public static bool IsDgvCellNull(object cellValue)
        {
            if (cellValue == null || cellValue == DBNull.Value)
                return true;
            return false;
        }

        ///　<summary>
        ///　打开MDI子窗口并附加到MDI主窗口中，如果MDI主窗口中已经存在相同类型的子窗口，则直接激活
        ///　</summary>
        ///　<typeparam　name="T">MDI子窗体类型</typeparam>
        ///　<param　name="mdiParent">MDI主窗体引用</param>
        ///　<returns>当前创建或得到的MDI子窗体类型实例的引用</returns>
        public static T ShowMDIChildForm<T>(Form mdiParent, Control frmContainer) where T : Form, new()
        {
            foreach (Form subForm in mdiParent.MdiChildren)
            {
                if (subForm.GetType().Equals(typeof(T)))
                {
                    subForm.Activate();
                    return subForm as T;
                }
            }

            T newForm = new T();
            newForm.MdiParent = mdiParent;
            newForm.Parent = frmContainer;
            newForm.Show();
            newForm.Activate();
            return newForm;
        }

        /// <summary>
        /// 打开MDI子窗口并附加到MDI主窗口中，如果MDI主窗口中已经存在相同类型的子窗口，则直接激活
        /// </summary>
        /// <param name="t"></param>
        /// <param name="mdiFrm"></param>
        public static void ShowMDIChildForm(Type t, Form mdiFrm)
        {
            foreach (Form subForm in mdiFrm.MdiChildren)
            {
                if (subForm.GetType().Equals(t))
                {
                    subForm.Activate();
                    subForm.BringToFront();
                    return;
                }
            }

            object obj = System.Activator.CreateInstance(t);
            Form frm = (Form)obj;
            frm.MdiParent = mdiFrm;
            frm.Show();
            frm.BringToFront();
        }

        /// <summary>
        /// 打开MDI子窗口并附加到MDI主窗口中，如果MDI主窗口中已经存在相同类型的子窗口，则直接激活
        /// </summary>
        /// <param name="t"></param>
        /// <param name="mdiFrm"></param>
        public static T GetMDIChildForm<T>(Form mdiFrm) where T : Form, new()
        {
            foreach (Form subForm in mdiFrm.MdiChildren)
            {
                if (subForm.GetType().Equals(typeof(T)))
                {
                    //subForm.Activate();
                    //subForm.BringToFront();
                    //return subForm as T;
                    if (subForm != null || !subForm.IsDisposed)
                        subForm.Close();
                    break;
                }
            }

            T frm = new T();
            frm.MdiParent = mdiFrm;
            frm.Activate();
            frm.BringToFront();
            return frm;
        }

        #region 系统业务
        /// <summary>
        /// 系统业务-实时检查工作单是否已提交
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public static bool BIZ_OrderIsSubmit(int orderId)
        {
            try
            {
                using (BaseDataClient bdc = new BaseDataClient())
                {
                    bdc.Open();
                    bool rtn = bdc.GetOrder(orderId).isSubmit;
                    bdc.Close();
                    return rtn;
                }
            }
            catch { }
            return false;
        }

        /// <summary>
        /// 系统业务-实时检查工作单是否已收款关闭
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        public static bool BIZ_OrderIsClosed(int orderId)
        {
            try
            {
                using (BaseDataClient bdc = new BaseDataClient())
                {
                    bdc.Open();
                    bool rtn = bdc.GetOrder(orderId).isClosed;
                    bdc.Close();
                    return rtn;
                }
            }
            catch { }
            return false;
        }

        /// <summary>
        /// 根据系统参数名称获取参数值
        /// </summary>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public static string BIZ_GetSysParamValue(EnumCommon.SysParamType paramType)
        {
            try
            {
                using (BaseDataClient bdc = new BaseDataClient())
                {
                    bdc.Open();
                    string rtn = bdc.GetSysParams().SingleOrDefault(p => p.paramName == paramType.ToString()).paramValue;
                    bdc.Close();
                    return rtn;
                }
            }
            catch { }
            return string.Empty;
        }
        #endregion
    }
    #endregion

    #region 委托自定义参数

    /// <summary>
    /// 通用自定义委托参数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class CommonEventArg<T> : EventArgs
    {
        /// <summary>
        /// 传递的参数
        /// </summary>
        public T t { get; set; }
        /// <summary>
        /// 委托操作类型
        /// </summary>
        public YY.UI.Common.OperateType OpType { get; set; }
        public CommonEventArg(T obj, YY.UI.Common.OperateType opType)
        {
            this.t = obj;
            this.OpType = opType;
        }
    }
    #endregion

    #region DataSet/对象相互转换
    /// <summary>   
    /// Represents some utility functions for object-datatable manipulation   
    /// </summary>   
    public sealed class OTConverter
    {
        /// <summary>
        /// 实体属性赋值到DataRow对应字段
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="t">实体</param>
        /// <param name="row">传入DataRow</param>
        public static void ObjectPropertyToDataRow<T>(T obj, DataColumnCollection dcs, DataRow dr)
        {
            try
            {
                Type t = obj.GetType(); //This is used to do the reflection   
                PropertyInfo[] props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                //dr.BeginEdit();
                foreach (PropertyInfo pro in props)
                {
                    if (dcs.Contains(pro.Name))
                    {
                        object value = pro.GetValue(obj, null);
                        dr[pro.Name] = value == null ? DBNull.Value : value;
                    }
                }
                //dr.EndEdit();
            }
            catch { }
        }

        public static DataRow CovertToDataRow<T>(T t, DataTable tb)
        {
            try
            {
                if (t != null && t is T)
                    return GetDataRow<T>(t, tb);
            }
            catch { }
            return null;
        }

        /// <summary>
        /// DataGridView转换成指定实体类结构的DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dgv"></param>
        /// <returns></returns>
        public static DataTable ConvertToDataTable<T>(DataGridView dgv) where T : new()
        {
            T obj = new T();
            DataTable dt = new DataTable(typeof(T).Name);
            System.Reflection.PropertyInfo[] myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
            {
                System.Reflection.PropertyInfo pi = myPropertyInfo[i];

                if (dt.Columns[pi.Name] == null)
                {
                    DataColumn dc = new DataColumn();
                    dc.AllowDBNull = true;
                    dc.ColumnName = pi.Name;
                    Type colType = pi.PropertyType;
                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                        colType = colType.GetGenericArguments()[0];
                    dc.DataType = colType;
                    dt.Columns.Add(dc);
                    //dt.Columns.Add(new DataColumn(name, pi.PropertyType));
                }
            }

            if (dgv.Rows.Count > 0)
            {
                for (int i = 0; i < dgv.Rows.Count; i++)
                {
                    DataRow row = dt.NewRow();
                    for (int j = 0; j < dgv.Rows[i].Cells.Count; j++)
                    {
                        if (ExistsColumnName(dt.Columns, dgv.Columns[j].Name))
                            row[dgv.Columns[j].Name] = dgv.Rows[i].Cells[j].Value;
                    }
                    dt.Rows.Add(row);
                }
            }
            return dt;
        }

        /// <summary>
        /// 实体架构映射到DataGirdView
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dgv"></param>
        public static void MapToDataGirdView<T>(DataGridView dgv, string[] notDisplays, object obj)
        {
            PropertyInfo[] proInfos = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            int colID;
            for (int i = 0; i < proInfos.Length; i++)
            {
                PropertyInfo pi = proInfos[i];
                //if (pi.IsDefined(typeof(ColumnVisibleAttribute), false)) 
                //{
                if (pi.PropertyType == obj.GetType())
                {
                    PropertyInfo[] childProps = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                    foreach (PropertyInfo p in childProps)
                    {
                        //ColumnVisibleAttribute colVis = p.GetCustomAttributes(typeof(ColumnVisibleAttribute), false)[0] as ColumnVisibleAttribute;
                        colID = dgv.Columns.Add(p.Name, p.Name);
                        dgv.Columns[colID].DataPropertyName = p.Name;
                        if (notDisplays.Contains(p.Name))
                            dgv.Columns[colID].Visible = false;
                    }
                }
                else
                {
                    //ColumnVisibleAttribute colVis = pi.GetCustomAttributes(typeof(ColumnVisibleAttribute), false)[0] as ColumnVisibleAttribute;
                    //colID = dgv.Columns.Add(pi.Name, colVis.CustomName);
                    //dgv.Columns[colID].DataPropertyName = pi.Name;
                    //if (notDisplays.Contains(pi.Name))
                    //    dgv.Columns[colID].Visible = false;
                }
                //} 
            }
        }

        /// <summary>
        /// DataGridView转换成指定实体类结构的序列
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dgv"></param>
        /// <returns></returns>
        public static List<T> ConvertDgvToObjectList<T>(DataGridView dgv, string[] notDisplays, object xObj) where T : new()
        {
            List<T> list = null;
            T obj = new T();
            System.Reflection.PropertyInfo[] myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            if (dgv.Rows.Count > 0)
            {
                list = new List<T>();
                for (int i = 0; i < dgv.Rows.Count; i++)
                {
                    T newObj = new T();
                    for (int p = 0, j = myPropertyInfo.Length; p < j; p++)
                    {
                        if (xObj != null && myPropertyInfo[p].PropertyType == xObj.GetType())
                        {
                            PropertyInfo[] childProps = (myPropertyInfo[p].GetValue(xObj, null)).GetType().GetProperties();
                            //PropertyInfo[] childProps = xObj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
                            foreach (PropertyInfo c in childProps)//子类
                            {
                                if (dgv.Columns[c.Name] != null && !notDisplays.Contains(c.Name))
                                {
                                    Type colType = c.PropertyType;
                                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                        colType = colType.GetGenericArguments()[0];
                                    object value = dgv.Rows[i].Cells[c.Name].Value;
                                    if (value != null)
                                    {
                                        object nValue = Convert.ChangeType(value, colType);
                                        c.SetValue(xObj, nValue, null);
                                    }
                                }
                            }
                        }

                        if (dgv.Columns[myPropertyInfo[p].Name] != null && !notDisplays.Contains(myPropertyInfo[p].Name))
                        {
                            Type colType = myPropertyInfo[p].PropertyType;
                            if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                colType = colType.GetGenericArguments()[0];
                            object value = dgv.Rows[i].Cells[myPropertyInfo[p].Name].Value;
                            if (value != null)
                            {
                                object nValue = Convert.ChangeType(value, colType);
                                myPropertyInfo[p].SetValue(newObj, nValue, null);
                            }
                        }
                    }
                    list.Add(newObj);
                }
            }
            return list;
        }

        /// <summary>   
        /// Convert an DataRow to an object   
        /// </summary>   
        /// <typeparam name="T"></typeparam>   
        /// <param name="row"></param>   
        /// <returns></returns>   
        public static T ConvertToObject<T>(DataRow row) where T : new()
        {
            object obj = new T();
            if (row != null)
            {
                DataTable t = row.Table;
                GetObject(t.Columns, row, obj);
            }
            if (obj != null && obj is T)
                return (T)obj;
            else
                return default(T);

        }

        /// <summary>   
        /// Convert a data table to an objct list   
        /// </summary>   
        /// <typeparam name="T"></typeparam>   
        /// <param name="t"></param>   
        /// <returns></returns>   
        public static List<T> ConvertTableToObject<T>(DataTable t) where T : new()
        {
            List<T> list = new List<T>();
            foreach (DataRow row in t.Rows)
            {
                T obj = ConvertToObject<T>(row);
                list.Add(obj);
            }

            return list;



        }

        /// <summary>   
        /// Convert object collection to an data table   
        /// </summary>   
        /// <param name="list"></param>   
        /// <returns></returns>   
        public static DataTable GenericListToDataTable(object list)
        {
            DataTable dt = null;
            Type listType = list.GetType();
            if (listType.IsGenericType)
            {
                //determine the underlying type the List<> contains   
                Type elementType = listType.GetGenericArguments()[0];

                //create empty table -- give it a name in case   
                //it needs to be serialized   
                dt = new DataTable(elementType.Name + "List");

                //define the table -- add a column for each public   
                //property or field   
                MemberInfo[] miArray = elementType.GetMembers(
                    BindingFlags.Public | BindingFlags.Instance);
                foreach (MemberInfo mi in miArray)
                {
                    if (mi.MemberType == MemberTypes.Property)
                    {
                        PropertyInfo pi = mi as PropertyInfo;
                        dt.Columns.Add(pi.Name, pi.PropertyType);
                    }
                    else if (mi.MemberType == MemberTypes.Field)
                    {
                        FieldInfo fi = mi as FieldInfo;
                        dt.Columns.Add(fi.Name, fi.FieldType);
                    }
                }

                //populate the table   
                IList il = list as IList;
                foreach (object record in il)
                {
                    int i = 0;
                    object[] fieldValues = new object[dt.Columns.Count];
                    foreach (DataColumn c in dt.Columns)
                    {
                        MemberInfo mi = elementType.GetMember(c.ColumnName)[0];
                        if (mi.MemberType == MemberTypes.Property)
                        {
                            PropertyInfo pi = mi as PropertyInfo;
                            fieldValues[i] = pi.GetValue(record, null);
                        }
                        else if (mi.MemberType == MemberTypes.Field)
                        {
                            FieldInfo fi = mi as FieldInfo;
                            fieldValues[i] = fi.GetValue(record);
                        }
                        i++;
                    }
                    dt.Rows.Add(fieldValues);
                }
            }
            return dt;
        }
        #region
        /// <summary>
        /// 将输入DataGridView中的数据转换成DataTable
        /// </summary>
        /// <param name="dgv">DataGridView控件</param>
        /// <returns>返回DataTable</returns>
        public static DataTable GetDgvToTable(DataGridView dgv)
        {
            DataTable dt = new DataTable();
            for (int count = 0; count < dgv.Rows.Count; count++)
            {
                DataRow dr = (dgv.Rows[count].DataBoundItem as DataRowView).Row;
                dt.Rows.Add(dr);
            }
            return dt;
        }
        #endregion


        #region "internal methods"
        private static void GetObject(DataColumnCollection cols, DataRow dr, Object obj)
        {
            Type t = obj.GetType(); //This is used to do the reflection   
            PropertyInfo[] props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
            //PropertyInfo[] props = t.GetProperties();
            foreach (PropertyInfo pro in props)
            {
                if (ExistsColumnName(cols, pro.Name))
                {
                    Type colType = pro.PropertyType;

                    pro.SetValue(obj,
                        dr[pro.Name] == DBNull.Value ? null : dr[pro.Name],
                        null);
                }
            }


            //for (Int32 i = 0; i <= cols.Count - 1; i++)   
            //{   
            //    try   
            //    {  //NOTE the datarow column names must match exactly (including case) to the object property names   
            //        t.InvokeMember(cols[i].ColumnName   
            //            , BindingFlags.SetProperty   
            //            , null   
            //            , obj   
            //            , new object[] { dr[cols[i].ColumnName] });   
            //    }   
            //    catch (Exception ex)   
            //    { //Usually you are getting here because a column doesn't exist or it is null   
            //        if (ex.ToString() != null)   
            //        {   
            //        }   
            //    }   
            //};   
        }

        private static DataRow GetDataRow<T>(T obj, DataTable tb)
        {
            try
            {
                DataRow dr = tb.NewRow();
                Type t = obj.GetType(); //This is used to do the reflection   
                PropertyInfo[] props = obj.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                //PropertyInfo[] props = t.GetProperties();
                foreach (PropertyInfo pro in props)
                {
                    if (ExistsColumnName(tb.Columns, pro.Name))
                        dr[pro.Name] = pro.GetValue(obj, null);
                }
            }
            catch { }
            return null;
        }

        private static bool ExistsColumnName(DataColumnCollection cols, string name)
        {
            foreach (DataColumn c in cols)
            {
                if (c.ColumnName.ToLower() == name.ToLower())
                    return true;
            }
            return false;
        }

        #endregion
    }
    #endregion

    #region IEnumerable扩充
    /// <summary>     
    /// IEnumerable 擴充方法     
    /// </summary>     
    public static class IEnumerableExtensions
    {
        /// <summary>     
        /// 將 IEnumerable 轉換至 DataTable     
        /// </summary>     
        /// <param name="list">IEnumerable</param>     
        /// <returns>DataTable</returns>     
        public static DataTable ToDataTable(this IEnumerable list)
        {
            DataTable dt = new DataTable();
            //bool schemaIsBuild = false;
            PropertyInfo[] props = null;
            bool isCreatedColumn = false;
            foreach (object item in list)
            {
                //if (!schemaIsBuild)
                //{
                ArrayList ary = new ArrayList();
                props = item.GetType().GetProperties();
                foreach (var pi in props)
                {
                    //if (ExistsColumnName(dt.Columns, pi.Name))
                    //    row[pi.Name] = pi.GetValue(item, null);
                    //dt.Columns.Add(new DataColumn(pi.Name, pi.PropertyType));

                    //dt.Rows.Add(row);
                    //schemaIsBuild = true;

                    if (pi.Name.ToLower() != "extensiondata")
                    {
                        if (!isCreatedColumn)
                        {
                            DataColumn dc = new DataColumn();
                            dc.AllowDBNull = true;
                            dc.ColumnName = pi.Name;
                            Type colType = pi.PropertyType;
                            if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                colType = colType.GetGenericArguments()[0];
                            dc.DataType = colType;
                            dt.Columns.Add(dc);
                        }


                        ary.Add(pi.GetValue(item, null));
                    }
                }
                object[] row = new object[ary.Count];
                ary.CopyTo(row);
                dt.Rows.Add(row);
                if (!isCreatedColumn)
                    isCreatedColumn = true;
                //}





                //var row = dt.NewRow();
                //foreach (var pi in props)
                //{
                //    row[pi.Name] = pi.GetValue(item, null);
                //}

                //dt.Rows.Add(row);
            }

            dt.AcceptChanges();
            return dt;
        }

        /// <summary>
        /// 把包含子类对象的复合类对象序列转换为DataTable,以便加载数据到控件
        /// </summary>
        /// <typeparam name="T">包含的子类对象</typeparam>
        /// <param name="list">复合类对象序列</param>
        /// <param name="dt">控件定义好架构的DataTable</param>
        /// <returns>DataTable</returns>
        public static DataTable ConvertToDataTable<T>(this IEnumerable list, DataTable dt)
        {
            //DataTable dt = new DataTable();
            bool schemaIsBuild = false;
            PropertyInfo[] props = null;

            foreach (object item in list)
            {
                if (!schemaIsBuild)
                {
                    DataRow row = dt.NewRow();
                    props = item.GetType().GetProperties();
                    foreach (PropertyInfo pi in props)
                    {
                        if (pi.PropertyType == typeof(T))
                        {
                            PropertyInfo[] childProps = ((T)pi.GetValue(item, null)).GetType().GetProperties();
                            foreach (PropertyInfo p in childProps)
                            {
                                if (ExistsColumnName(dt.Columns, pi.Name))
                                    row[p.Name] = p.GetValue(pi, null);
                            }
                        }
                        else
                        {
                            if (ExistsColumnName(dt.Columns, pi.Name))
                                row[pi.Name] = pi.GetValue(item, null);
                        }
                    }

                    dt.Rows.Add(row);
                    schemaIsBuild = true;
                }
            }
            dt.AcceptChanges();
            return dt;
        }

        /// <summary>
        /// 把包含子类对象的复合类对象序列转换为DataTable,以便加载数据到控件
        /// </summary>
        /// <typeparam name="T">包含的子类对象</typeparam>
        /// <param name="list">复合类对象序列</param>
        /// <returns>DataTable</returns>
        public static DataTable ConvertToDataTable<T>(this IEnumerable list)
        {
            DataTable dt = new DataTable();
            //bool schemaIsBuild = false;
            PropertyInfo[] props = null;
            bool isCreatedColumn = false;

            //Array.ForEach<PropertyInfo>(list.get.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });

            foreach (object item in list)
            {
                //if (!schemaIsBuild)
                //{
                ArrayList ary = new ArrayList();
                //DataRow row = dt.NewRow();
                props = item.GetType().GetProperties();
                foreach (PropertyInfo pi in props)
                {
                    if (pi.PropertyType == typeof(T))
                    {
                        PropertyInfo[] childProps = ((T)pi.GetValue(item, null)).GetType().GetProperties();
                        foreach (PropertyInfo p in childProps)
                        {
                            if (p.Name.ToLower() != "extensiondata")
                            {
                                if (!isCreatedColumn)
                                {
                                    DataColumn dc = new DataColumn();
                                    dc.AllowDBNull = true;
                                    dc.ColumnName = p.Name;
                                    Type colType = p.PropertyType;
                                    if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                        colType = colType.GetGenericArguments()[0];
                                    dc.DataType = colType;
                                    dt.Columns.Add(dc);
                                }
                                ary.Add(p.GetValue((T)pi.GetValue(item, null), null));
                                //dt.Columns.Add(new DataColumn(p.Name, p.PropertyType));
                                //row[p.Name] = p.GetValue(pi, null);
                            }
                        }
                    }
                    else
                    {
                        if (pi.Name.ToLower() != "extensiondata")
                        {
                            if (!isCreatedColumn)
                            {
                                DataColumn dc = new DataColumn();
                                dc.AllowDBNull = true;
                                dc.ColumnName = pi.Name;
                                Type colType = pi.PropertyType;
                                if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                                    colType = colType.GetGenericArguments()[0];
                                dc.DataType = colType;
                                dt.Columns.Add(dc);
                            }


                            ary.Add(pi.GetValue(item, null));
                        }
                    }
                }
                object[] row = new object[ary.Count];
                ary.CopyTo(row);
                dt.Rows.Add(row);
                if (!isCreatedColumn)
                    isCreatedColumn = true;
                //schemaIsBuild = true;
                //}
            }
            dt.AcceptChanges();
            return dt;
        }

        private static bool ExistsColumnName(DataColumnCollection cols, string name)
        {
            foreach (DataColumn c in cols)
            {
                if (c.ColumnName.ToLower() == name.ToLower())
                    return true;
            }
            return false;
        }
    }
    #endregion

    #region 自定义属性
    [global::System.AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
    public sealed class ColumnVisibleAttribute : Attribute
    {
        public ColumnVisibleAttribute(string custom) : this(custom, true) { }
        public ColumnVisibleAttribute(string customName, bool isDisplay) { this._customName = customName; this._display = IsDisplay; }
        private bool _display;
        public bool IsDisplay { get { return _display; } set { _display = value; } }
        private string _customName;
        public string CustomName { get { return _customName; } set { _customName = value; } }
    }
    #endregion

    #region DataGridView自定义类
    public delegate void CheckBoxClickedHandler(bool state);
    public class DataGridViewCheckBoxHeaderCellEventArgs : EventArgs
    {
        bool _bChecked;
        public DataGridViewCheckBoxHeaderCellEventArgs(bool bChecked)
        {
            _bChecked = bChecked;
        }
        public bool Checked
        {
            get { return _bChecked; }
        }
    }
    class DataGridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell
    {
        Point checkBoxLocation;
        Size checkBoxSize;
        bool _checked = false;
        Point _cellLocation = new Point();
        System.Windows.Forms.VisualStyles.CheckBoxState _cbState =
            System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
        public event CheckBoxClickedHandler OnCheckBoxClicked;

        public DataGridViewCheckBoxHeaderCell()
        {
        }

        protected override void Paint(System.Drawing.Graphics graphics,
            System.Drawing.Rectangle clipBounds,
            System.Drawing.Rectangle cellBounds,
            int rowIndex,
            DataGridViewElementStates dataGridViewElementState,
            object value,
            object formattedValue,
            string errorText,
            DataGridViewCellStyle cellStyle,
            DataGridViewAdvancedBorderStyle advancedBorderStyle,
            DataGridViewPaintParts paintParts)
        {
            base.Paint(graphics, clipBounds, cellBounds, rowIndex,
                dataGridViewElementState, value,
                formattedValue, errorText, cellStyle,
                advancedBorderStyle, paintParts);
            Point p = new Point();
            Size s = CheckBoxRenderer.GetGlyphSize(graphics,
            System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
            p.X = cellBounds.Location.X +
                (cellBounds.Width / 2) - (s.Width / 2);
            p.Y = cellBounds.Location.Y +
                (cellBounds.Height / 2) - (s.Height / 2);
            _cellLocation = cellBounds.Location;
            checkBoxLocation = p;
            checkBoxSize = s;
            if (_checked)
                _cbState = System.Windows.Forms.VisualStyles.
                    CheckBoxState.CheckedNormal;
            else
                _cbState = System.Windows.Forms.VisualStyles.
                    CheckBoxState.UncheckedNormal;
            CheckBoxRenderer.DrawCheckBox
            (graphics, checkBoxLocation, _cbState);
        }

        protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
        {
            Point p = new Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y);
            if (p.X >= checkBoxLocation.X && p.X <=
                checkBoxLocation.X + checkBoxSize.Width
            && p.Y >= checkBoxLocation.Y && p.Y <=
                checkBoxLocation.Y + checkBoxSize.Height)
            {
                _checked = !_checked;
                if (OnCheckBoxClicked != null)
                {
                    OnCheckBoxClicked(_checked);
                    this.DataGridView.InvalidateCell(this);
                }

            }
            base.OnMouseClick(e);
        }
    }

    #endregion
}
